package cn.com.zzl.chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cn.com.zzl.util.AssertUtil;

/**
 * @description 服务端
 * @author rambo
 * @date 2018年9月26日 下午4:36:35
 */
public class TCPServer {
	
	/**
	 * @description 服务端Socket
	 */
	private ServerSocket serverSocket;
	
	/**
	 * @description 创建线程池来管理客户端的连接线程，避免系统资源过度浪费
	 */
	private ExecutorService exec;
	
	/**
	 * @description 存放客户端之间私聊的信息
	 */
	private Map<String, PrintWriter> storeInfo;
	
	/**
	 * @description 自定义构造函数
	 */
	public TCPServer() {
		try {
			serverSocket = new ServerSocket(6789);
			storeInfo = new HashMap<String, PrintWriter>();
			exec = Executors.newCachedThreadPool();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @description 将客户端的信息以Map形式存入集合中
	 * @param key 键
	 * @param value 值
	 */
	private void putIn(String key, PrintWriter value) {
		synchronized (this) {
			storeInfo.put(key, value);
		}
	}
	
	/**
	 * @description 将给定的输出流从共享集合中删除
	 * @param key 键
	 */
	private synchronized void remove(String key) {
		storeInfo.remove(key);
		System.out.println("当前在线人数为：" + storeInfo.size());
	}
	
	/**
	 * @description 将给定的消息转发给所有客户端
	 * @param message
	 */
	private synchronized void sendToAll(String message) {
		for (PrintWriter out : storeInfo.values()) {
			out.println(message);
		}
	}
	
	/**
	 * @description 将给定的消息转发给私聊的客户端
	 * @param name
	 * @param message
	 */
	private synchronized void sendToSomeone(String name, String message) {
		PrintWriter pw = storeInfo.get(name);
		if (AssertUtil.isNotEmpty(pw)) {
			pw.println(message);
		}
	}
	
	/**
	 * @description TODO
	 */
	public void start() {
		try {
			while (true) {
				System.out.println("等待客户端连接... ...");
				Socket socket = serverSocket.accept();
				
				//获取客户端的ip地址
				InetAddress address = socket.getInetAddress();
				System.out.println("客户端：" + address.getHostAddress() + "连接成功！");
				
				//启动一个线程，由线程来处理客户端的请求，这样可以再次监听下一个客户端的连接
				exec.execute(new ListenerClient(socket));//通过线程池来分配线程
			}	
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @description 该线程体用来处理给定的某一个客户端的消息，循环接收客户端发送每一个字符串，并输出到控制台
	 * @author rambo
	 * @date 2018年9月26日 下午5:20:30
	 */
	class ListenerClient implements Runnable {
		private Socket socket;
		private String name;
		
		public ListenerClient(Socket socket) {
			this.socket = socket;
		}
		
		/**
		 * @description 创建内部类来获取昵称
		 * @return
		 */
		private String getName() {
			try {
				//服务端的输入流读取客户端发送来的昵称输出流
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
				
				//服务端将昵称验证结果通过自身的输出流发送给客户端
				PrintWriter pWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);
				
				//读取客户端发来的昵称
				while (true) {
					String nameString = bufferedReader.readLine();
					if (nameString.trim().length() == 0 || storeInfo.containsKey(nameString)) {
						pWriter.println("FAIL");
					} else {
						pWriter.println("OK");
						return nameString;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			} 
			return "";
		}

		@Override
		public void run() {
			
		}
	}
	
	

}
